package com.fihtdc.excelreader;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.read.biff.BiffException;

public class ExcelReader {
    private final String           MLF_FILE_NAME_FORMAT     = "-VV-0-MM-A01.mlf";
    private final String           CONFIG_FILE_NAME         = "collection.conf";
    private final String           REF_COL_NAME             = "File Name";
    private final String           ADD_COL_NAME             = " reserved File";
    private final String           SHEET_MAIN               = "main";
    private final String           SHEET_MODEL_CONFIG       = "model-config";
    private final int              INDEX_REF_ROW            = 1;
    private final int              INDEX_CONFIG_START_ROW   = 2;

    // model-config sheet
    private final int              INDEX_MODEL_SELECT       = 1;

    // model sheet
    private final int              INDEX_MODEL_START_ROW    = 2;
    private final int              INDEX_MODEL_SRART_COLUMN = 1;

    private final String           KEY_PLATFORM_CODE        = "Android platform";
    private final String           KEY_PROJECT_CODE         = "Project_Code";
    private final String           KEY_MODEL_CODE           = "MODEL_CODE";
    private final String           KEY_IMAGE_TYPE           = "SystemImg";
    private final String           KEY_TARGET_PRODUCT       = "TARGET_PRODUCT";
    private final String           KEY_ODEX                 = "ODEX";
    private final String           KEY_CERT_OPTION          = "CERT-OPTION";

    private ArrayList<ModelDetail> packList;

    private String                 inputFile;
    private String                 outputFolder;

    private boolean                isMoto                   = false;
    private boolean                isMTK                    = false;

    public ExcelReader(String excel, String output) {
        packList = new ArrayList<ModelDetail>();
        this.inputFile = excel;
        this.outputFolder = output;

        read();
        int fileConfExist = genConf(packList);
        int fileTxtExist = genModelTxt(packList);
        System.out.println("Gen " + fileConfExist + " collection.conf, " + fileTxtExist + " txts");
    }

    public void read() {
        int INDEX_ROW_IMAGETYPE;
        int INDEX_COL_IMAGETYPE;

        int INDEX_MODEL_CODE;
        int INDEX_TAEGET_PRODUCT;
        int INDEX_ODEX;
        int INDEX_CERT_OPTION;

        String PLATFORM_CODE;
        String PROJECT_CODE;

        try {
            // discard Warning: Cannot find drawing record - using continue record
            WorkbookSettings setting = new WorkbookSettings();
            setting.setSuppressWarnings(true);
            Workbook buildExcel = Workbook.getWorkbook(new File(inputFile), setting);
            // read Android platform, Project_Code and Img_Profile_Type in main
            // sheet
            Sheet _main = buildExcel.getSheet(SHEET_MAIN);
            int INDEX_ROW_ANDROID_PLATFORM = _main.findCell(KEY_PLATFORM_CODE).getRow();
            int INDEX_COL_ANDROID_PLATFORM = _main.findCell(KEY_PLATFORM_CODE).getColumn() + 1;
            PLATFORM_CODE = _main.getCell(INDEX_COL_ANDROID_PLATFORM, INDEX_ROW_ANDROID_PLATFORM)
                    .getContents();
            int INDEX_ROW_PROJECT_CODE = _main.findCell(KEY_PROJECT_CODE).getRow();
            int INDEX_COL_PROJECT_CODE = _main.findCell(KEY_PROJECT_CODE).getColumn() + 1;
            PROJECT_CODE = _main.getCell(INDEX_COL_PROJECT_CODE, INDEX_ROW_PROJECT_CODE)
                    .getContents();
            // project special case
            if (PROJECT_CODE.equals("SFC2030") || PROJECT_CODE.equals("SFC4040")) {
                PROJECT_CODE = "SFC";
            } else if (PROJECT_CODE.equals("SH82030") || PROJECT_CODE.equals("SH84040")) {
                PROJECT_CODE = "SH8";
            } else if (PROJECT_CODE.equals("FB02030")) {
                PROJECT_CODE = "FB0";
            } else if (PROJECT_CODE.equals("SF82030")) {
                PROJECT_CODE = "SF8";
            }

            isMoto = isMotoProject(PROJECT_CODE);
            isMTK = isMTKProject(PROJECT_CODE);

            System.out.println(PROJECT_CODE + " start parsing");
            System.out.println("read conf ===>");

            // generate PROJECT_CODE folder
            genConfigFolder(PROJECT_CODE);

            // read pack model
            Sheet _modelConfig = buildExcel.getSheet(SHEET_MODEL_CONFIG);

            INDEX_MODEL_CODE = _modelConfig.findCell(KEY_MODEL_CODE).getColumn();
            INDEX_TAEGET_PRODUCT = _modelConfig.findCell(KEY_TARGET_PRODUCT).getColumn();
            INDEX_ODEX = _modelConfig.findCell(KEY_ODEX).getColumn();
            INDEX_CERT_OPTION = (_modelConfig.findCell(KEY_CERT_OPTION) == null) ? -1
                    : _modelConfig.findCell(KEY_CERT_OPTION).getColumn();

            int unblankRowNum = getUnblankRows(_modelConfig, INDEX_MODEL_CODE);

            for (int start_row = INDEX_CONFIG_START_ROW; start_row < unblankRowNum; start_row++) {
                String selected = _modelConfig.getCell(INDEX_MODEL_SELECT, start_row).getContents();
                if (Boolean.parseBoolean(selected)) {
                    ModelDetail gd = new ModelDetail();
                    Model model = new Model();

                    model.setProjectCode(PROJECT_CODE);
                    String model_code = _modelConfig.getCell(INDEX_MODEL_CODE, start_row)
                            .getContents();
                    model.setModelCode(model_code);

                    Sheet _model = buildExcel.getSheet(PROJECT_CODE + "_" + model_code);
                    INDEX_COL_IMAGETYPE = _model.findCell(KEY_IMAGE_TYPE).getColumn() - 1;
                    INDEX_ROW_IMAGETYPE = _model.findCell(KEY_IMAGE_TYPE).getRow();
                    String[] system_img = _model.getCell(INDEX_COL_IMAGETYPE, INDEX_ROW_IMAGETYPE)
                            .getContents().split("\\.");
                    String imagetype = system_img[system_img.length - 1];
                    model.setImageType(imagetype);

                    String odex = _modelConfig.getCell(INDEX_ODEX, start_row).getContents();
                    model.setGenOdex(odex);
                    model.setSignKey("true");
                    String kernel = _modelConfig.getCell(INDEX_TAEGET_PRODUCT, start_row)
                            .getContents();
                    model.setKernel(kernel);
                    model.setPlatForm(PLATFORM_CODE.toLowerCase());

                    if (isMTK) {
                        String certOption = _modelConfig.getCell(INDEX_CERT_OPTION, start_row)
                                .getContents();
                        model.setCertOption(certOption);
                    }

                    gd.setModel(model);
                    packList.add(gd);
                }
            }
            System.out.println("<===read conf end");

            readModel(buildExcel);
            buildExcel.close();
        } catch (BiffException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }

    private void genConfigFolder(String project_code) {
        File model_folder = new File(outputFolder + "/" + project_code);
        if (model_folder.exists()) {
            try {
                deleteConfFolder(model_folder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            model_folder.mkdirs();
            System.out.println(project_code + " folder generated");
        } else {
            model_folder.mkdirs();
        }
    }

    private void deleteConfFolder(File folder) throws IOException {
        String[] files = folder.list();
        for (String file : files) {
            File subfile = new File(folder, file);
            if (subfile.isDirectory()) {
                deleteConfFolder(subfile);
            }
            subfile.delete();
        }
        folder.delete();
    }

    private void readModel(Workbook buildExcel) throws BiffException, IOException {
        System.out.println("start read model detail===>");
        for (ModelDetail gen : packList) {
            int row = INDEX_MODEL_START_ROW;
            int col = INDEX_MODEL_SRART_COLUMN;

            Sheet modelSheet = buildExcel.getSheet(gen.getModel().getProjectCode() + "_"
                    + gen.getModel().getModelCode());

            boolean reservedFileFlag = (!(modelSheet.findCell(ADD_COL_NAME) == null)) ? true
                    : false;
            System.out.println("reserved File column = " + reservedFileFlag);
            int H = getUnblankRows(modelSheet);
            for (int i = col; i < modelSheet.getColumns(); i++) {
                if (i == 4) {
                    continue;
                }
                ArrayList<String> att = new ArrayList<String>();

                for (int j = row; j < H; j++) {
                    att.add(modelSheet.getCell(i, j).getContents());
                }

                gen.setAttr(att, i);
            }
            if (!reservedFileFlag) {
                ArrayList<String> blankList = new ArrayList<String>();
                for (int k = 0; k < gen.getFileName().size(); k++) {
                    blankList.add("");
                }
                gen.setReservedFile(blankList);
            }
        }
        System.out.println("<=== read model detail end");
    }

    private int getUnblankRows(Sheet s) {
        int realRows = 0;
        int indexOfH = s.findCell(REF_COL_NAME, 0, 0, s.getColumns(), INDEX_REF_ROW, false)
                .getColumn();

        for (Cell c : s.getColumn(indexOfH)) {
            if (!c.getContents().equals("") || c.getRow() == 0) {
                realRows++;
            } else {
                break;
            }
        }
        return realRows;
    }

    private int getUnblankRows(Sheet s, int refIndex) {
        int realRows = 0;
        for (Cell c : s.getColumn(refIndex)) {
            if (!c.getContents().equals("") || c.getRow() == 0) {
                realRows++;
            } else {
                break;
            }
        }
        return realRows;
    }

    /*
     * =================== collection.conf file format ====================
     * Project=* Model=* ImageType=* GenOdex=* SignKey=* Kernel=* PlatForm=*
     */
    public int genConf(ArrayList<ModelDetail> model_list) {
        FileWriter fw;
        int conf = -1;
        try {
            File conf_doc = new File(outputFolder + "/"
                    + model_list.get(0).getModel().getProjectCode() + "/" + CONFIG_FILE_NAME);

            fw = new FileWriter(conf_doc);

            for (ModelDetail modelDetail : model_list) {
                Model model = modelDetail.getModel();
                fw.write("Project=" + model.getProjectCode() + " Model=" + model.getModelCode()
                        + " ImageType=" + model.getImageType() + " GenOdex=" + model.getGenOdex()
                        + " SignKey=" + model.getSignKey() + " Kernel=" + model.getKernel()
                        + " PlatForm=" + model.getPlatForm() + " ");
                if (isMTK) {
                    fw.write("CERT_OPTION=" + model.getCertOption());
                }
                if (!model.equals(model_list.get(model_list.size() - 1))) {
                    fw.write("\n");
                }
            }
            fw.close();
            conf = conf_doc.exists() ? 1 : 0;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return conf;
    }

    /*
     * ================ <PROJECT_CODE>_<MODEL_CODE> file format=================
     * MLF,<PROJECT_CODE>-VV-0-MM-A01.mlf Component Type,Project,Component
     * Name,,Component ID,Version,FileName,FileType,sign key, ,integrating
     * options,reserved File modem ,sfc ,mprg ,,sfc , ,sfc ,mode ,* ,*, , ,
     */
    public int genModelTxt(ArrayList<ModelDetail> model_list) {
        int txt = 0;
        String doc = outputFolder + "/" + model_list.get(0).getModel().getProjectCode();
        File txt_doc;
        try {
            FileWriter fw;
            for (ModelDetail modelDetail : model_list) {
                Model model = modelDetail.getModel();
                txt_doc = new File(doc + "/" + model.getProjectCode() + "_" + model.getModelCode()
                        + ".txt");
                fw = new FileWriter(txt_doc);
                fw.write("MLF," + model.getProjectCode() + MLF_FILE_NAME_FORMAT + "\n");
                for (int i = 0; i < modelDetail.getFileName().size(); i++) {
                    fw.write(modelDetail.getComponentType().get(i) + ","
                            + modelDetail.getProject().get(i) + ","
                            + modelDetail.getComponentName().get(i) + ",,"
                            + modelDetail.getComponentId().get(i) + ","
                            + modelDetail.getVersion().get(i) + ","
                            + modelDetail.getFileName().get(i) + ","
                            + modelDetail.getFileType().get(i) + ","
                            + modelDetail.getSignKey().get(i) + ","
                            + modelDetail.getIntergratingOptions().get(i) + ",");
                    if (isMoto) {
                        fw.write("\n");
                    } else {
                        fw.write(modelDetail.getReservedFile().get(i) + ",\n");
                    }
                }
                fw.close();
                txt = txt_doc.exists() ? txt + 1 : txt;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return txt;
    }

    private boolean isMotoProject(String project_code) {
        boolean flag = false;
        if (project_code.equals("AI1S") || project_code.equals("FAD") || project_code.equals("DMT")
                || project_code.equals("DP2") || project_code.equals("DQD")
                || project_code.equals("FB0") || project_code.equals("DMQ")) {
            flag = true;
        }
        return flag;
    }

    private boolean isMTKProject(String project_code) {
        boolean flag = false;
        if (project_code.equals("FAR")) {
            flag = true;
        }
        return flag;
    }

    public static void main(String[] args) {
        try {
            new ExcelReader(args[0], args[1]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("$1:image shelf excel location\n" + "$2:conf & txt output location");
        }
    }
}